package main

import (
	"admission-webhook-demo/logger"
	"admission-webhook-demo/webhook"
	"context"
	"crypto/tls"
	"flag"
	"fmt"
	"go.uber.org/zap"
	"net/http"
	"os"
	"os/signal"
	"syscall"
)

// params 命令行参数
type params struct {
	port        int
	certFile    string
	keyFile     string
	verbose     bool
	privateRepo string
}

func main() {
	var params params
	flag.StringVar(&params.certFile, "cert_file", "/etc/webhook/certs/tls.crt", "HTTPS x509 证书文件位置")
	flag.StringVar(&params.keyFile, "key_file", "/etc/webhook/certs/tls.key", "HTTPS x509 私钥文件位置")
	flag.BoolVar(&params.verbose, "verbose", false, "是否开启详细日志")
	flag.IntVar(&params.port, "port", 443, "监听端口")
	flag.StringVar(&params.privateRepo, "private_repo", "", "私有仓库地址")
	flag.Parse()

	logger.Init(params.verbose)
	zap.L().Info(
		"Starting webhook server...",
		zap.String("cert_file", params.certFile),
		zap.String("key_file", params.keyFile),
		zap.Int("port", params.port),
		zap.Bool("verbose", params.verbose),
		zap.String("private_repo", params.privateRepo),
	)

	var server *http.Server
	pair, err := tls.LoadX509KeyPair(params.certFile, params.keyFile)
	if err != nil {
		zap.L().Error(
			"LoadX509KeyPair failed",
			zap.String("certFile", params.certFile),
			zap.String("keyFile", params.keyFile),
			zap.Error(err),
		)
		return
	}
	server = &http.Server{
		Addr:      fmt.Sprintf(":%v", params.port),
		TLSConfig: &tls.Config{Certificates: []tls.Certificate{pair}},
	}

	// 启动httpserver
	ws := &webhook.WhServer{Server: server, PrivateRepo: params.privateRepo}
	mux := http.NewServeMux()
	mux.HandleFunc("/mutate", ws.Serve)
	mux.HandleFunc("/validate", ws.Serve)
	ws.Server.Handler = mux

	go func() {
		if err := ws.Server.ListenAndServeTLS("", ""); err != nil {
			zap.L().Error("ListenAndServeTLS failed", zap.Error(err))
		}
	}()
	zap.L().Info("Server started")

	// 优雅退出
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
	<-signalChan

	zap.L().Info("Got OS shutdown signal, shutting down webhook server gracefully...")
	if err := ws.Server.Shutdown(context.Background()); err != nil {
		zap.L().Error("Shutdown failed", zap.Error(err))
		return
	}
}
